import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:intl/intl.dart' hide TextDirection;

// 100天时间范围的滑动时间刻度组件
class HundredDaysTimeScale extends LeafRenderObjectWidget {
  // 组件高度
  final double height;
  // 可视宽度
  final double visibleWidth;
  // 起始日期（100天的起点）
  final DateTime startDate;
  // 初始选中日期
  final DateTime initialDate;
  // 日期变化回调
  final ValueChanged<DateTime>? onDateChanged;
  // 每天占用的像素宽度
  final double dayPixelWidth;
  // 是否显示星期信息
  final bool showWeekday;

   HundredDaysTimeScale({
    super.key,
    this.height = 140.0,
    this.visibleWidth = 350.0,
    required this.startDate,
    DateTime? initialDate,
    this.onDateChanged,
    this.dayPixelWidth = 60.0,
    this.showWeekday = true,
  }) : initialDate = initialDate ?? startDate,
        assert(_isValidDateRange(startDate, initialDate ?? startDate));

  // 验证日期范围是否在100天内
  static bool _isValidDateRange(DateTime start, DateTime initial) {
    final days = initial.difference(start).inDays;
    return days >= 0 && days <= 100;
  }

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderHundredDaysTimeScale(
      height: height,
      visibleWidth: visibleWidth,
      startDate: startDate,
      initialDate: initialDate,
      onDateChanged: onDateChanged,
      dayPixelWidth: dayPixelWidth,
      showWeekday: showWeekday,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderHundredDaysTimeScale renderObject) {
    renderObject
      ..height = height
      ..visibleWidth = visibleWidth
      ..startDate = startDate
      ..dayPixelWidth = dayPixelWidth
      ..showWeekday = showWeekday
      ..onDateChanged = onDateChanged;
  }
}

// 100天时间刻度渲染对象
class RenderHundredDaysTimeScale extends RenderBox {
  double _height;
  double _visibleWidth;
  DateTime _startDate;
  DateTime _currentDate;
  ValueChanged<DateTime>? _onDateChanged;
  double _dayPixelWidth;
  bool _showWeekday;
  
  // 滑动偏移量
  double _offsetX = 0.0;
  // 最大可滑动偏移量（100天总宽度 - 可视宽度）
  double get _maxOffsetX => _totalWidth - _visibleWidth;
  // 100天的总宽度
  double get _totalWidth => 100 * _dayPixelWidth;
  
  // 触摸状态
  double? _startTouchX;
  double? _startOffsetX;
  bool _isDragging = false;

  // 计算日期对应的偏移量
  double _getDateOffset(DateTime date) {
    final days = date.difference(_startDate).inDays;
    return days.clamp(0, 100) * _dayPixelWidth;
  }

  // 根据偏移量计算对应的日期
  DateTime _getOffsetDate(double offset) {
    final clampedOffset = offset.clamp(0.0, _maxOffsetX);
    final days = (clampedOffset / _dayPixelWidth).round();
    return _startDate.add(Duration(days: days));
  }

  RenderHundredDaysTimeScale({
    required double height,
    required double visibleWidth,
    required DateTime startDate,
    required DateTime initialDate,
    ValueChanged<DateTime>? onDateChanged,
    required double dayPixelWidth,
    required bool showWeekday,
  })  : _height = height,
        _visibleWidth = visibleWidth,
        _startDate = startDate,
        _currentDate = _clampDate(initialDate, startDate),
        _onDateChanged = onDateChanged,
        _dayPixelWidth = dayPixelWidth,
        _showWeekday = showWeekday {
    // 计算初始偏移量
    _offsetX = _getDateOffset(_currentDate);
  }

  // 将日期限制在100天范围内
  static DateTime _clampDate(DateTime date, DateTime startDate) {
    final days = date.difference(startDate).inDays;
    if (days < 0) return startDate;
    if (days > 100) return startDate.add(const Duration(days: 100));
    return date;
  }

  // 设置属性的setter
  set height(double value) {
    if (_height != value) {
      _height = value;
      markNeedsLayout();
    }
  }

  set visibleWidth(double value) {
    if (_visibleWidth != value) {
      _visibleWidth = value;
      markNeedsLayout();
    }
  }

  set startDate(DateTime value) {
    if (!_startDate.isAtSameMomentAs(value)) {
      _startDate = value;
      // 重新计算当前日期和偏移量
      _currentDate = _clampDate(_currentDate, value);
      _offsetX = _getDateOffset(_currentDate);
      markNeedsPaint();
    }
  }

  set dayPixelWidth(double value) {
    if (_dayPixelWidth != value && value > 0) {
      _dayPixelWidth = value;
      _offsetX = _getDateOffset(_currentDate);
      markNeedsLayout();
    }
  }

  set showWeekday(bool value) {
    if (_showWeekday != value) {
      _showWeekday = value;
      markNeedsPaint();
    }
  }

  set onDateChanged(ValueChanged<DateTime>? value) {
    _onDateChanged = value;
  }

  // 限制偏移量在有效范围内
  void _clampOffset() {
    _offsetX = _offsetX.clamp(0.0, _maxOffsetX);
  }

  // 吸附到最近的日期
  void _snapToDate() {
    final days = (_offsetX / _dayPixelWidth).round();
    _offsetX = days * _dayPixelWidth;
    _clampOffset();
    
    // 更新当前日期并通知
    final newDate = _getOffsetDate(_offsetX);
    if (!_currentDate.isAtSameMomentAs(newDate)) {
      _currentDate = newDate;
      _onDateChanged?.call(_currentDate);
    }
    
    markNeedsPaint();
  }

  // 处理触摸事件
  @override
  bool hitTestSelf(Offset position) => true;

  @override
  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
    super.handleEvent(event, entry);

    if (event is PointerDownEvent) {
      _startTouchX = event.localPosition.dx;
      _startOffsetX = _offsetX;
      _isDragging = true;
    } else if (event is PointerMoveEvent && _startTouchX != null && _startOffsetX != null) {
      // 计算滑动偏移
      final deltaX = event.localPosition.dx - _startTouchX!;
      _offsetX = _startOffsetX! - deltaX; // 反向滑动
      
      _clampOffset();
      markNeedsPaint();
    } else if ((event is PointerUpEvent || event is PointerCancelEvent) && _isDragging) {
      _isDragging = false;
      _startTouchX = null;
      _startOffsetX = null;
      
      // 滑动结束后吸附到最近的日期
      _snapToDate();
    }
  }

  // 布局逻辑
  @override
  void performLayout() {
    size = Size(_visibleWidth, _height);
  }

  // 绘制日期刻度
  void _paintDateScale(Canvas canvas, Offset offset) {
    final mainPaint = Paint()
      ..color = Colors.black87
      ..strokeWidth = 1.5;
      
    final weekPaint = Paint()
      ..color = Colors.blueAccent
      ..strokeWidth = 2.0;

    print("offset $_offsetX");

    // 刻度高度
    const mainScaleHeight = 35.0;
    const weekScaleHeight = 45.0;
    final centerY = offset.dy + _height / 2;

    // 计算可见范围内的日期
    final startDay = (_offsetX / _dayPixelWidth).floor() - 1;
    final endDay = ((_offsetX + _visibleWidth) / _dayPixelWidth).ceil() + 1;

    // 绘制可见范围内的刻度
    for (int day = startDay; day <= endDay; day++) {
      // 跳过超出100天范围的日期
      if (day < 0 || day > 100) continue;
      
      final x = offset.dx + (day * _dayPixelWidth) - _offsetX;
      final date = _startDate.add(Duration(days: day));
      
      // 判断是否为周末
      final isWeekend = date.weekday == DateTime.saturday || date.weekday == DateTime.sunday;
      // 判断是否为每周第一天（周一）
      final isWeekStart = date.weekday == DateTime.monday;
      
      // 选择画笔（周末用特殊颜色，每周开始用更长刻度）
      final paint = isWeekStart ? weekPaint : mainPaint;
      final scaleHeight = isWeekStart ? weekScaleHeight : mainScaleHeight;
      
      // 绘制刻度线
      canvas.drawLine(
        Offset(x, centerY - scaleHeight),
        Offset(x, centerY + scaleHeight),
        paint,
      );
      
      // 绘制日期文本
      final dateFormatter = DateFormat('d'); // 日
      final dateText = dateFormatter.format(date);
      
      final textPainter = TextPainter(
        text: TextSpan(
          text: dateText,
          style: TextStyle(
            color: isWeekend ? Colors.red : Colors.black87,
            fontSize: 12,
            fontWeight: isWeekStart ? FontWeight.bold : FontWeight.normal,
          ),
        ),
        textDirection: TextDirection.ltr,
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(
          x - textPainter.width / 2,
          centerY + scaleHeight + 5,
        ),
      );
      
      // 绘制星期文本（可选）
      if (_showWeekday && isWeekStart) {
        final weekdayFormatter = DateFormat('E'); // 星期缩写
        final weekdayText = weekdayFormatter.format(date);
        
        final weekdayPainter = TextPainter(
          text: TextSpan(
            text: weekdayText,
            style: const TextStyle(
              color: Colors.blueAccent,
              fontSize: 10,
              fontWeight: FontWeight.bold,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        weekdayPainter.layout();
        weekdayPainter.paint(
          canvas,
          Offset(
            x - weekdayPainter.width / 2,
            centerY - scaleHeight - 15,
          ),
        );
      }
      
      // 每月第一天绘制月份信息
      if (date.day == 1) {
        final monthFormatter = DateFormat('MMM'); // 月份缩写
        final monthText = monthFormatter.format(date);
        
        final monthPainter = TextPainter(
          text: TextSpan(
            text: monthText,
            style: const TextStyle(
              color: Colors.green,
              fontSize: 12,
              fontWeight: FontWeight.bold,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        monthPainter.layout();
        monthPainter.paint(
          canvas,
          Offset(
            x - monthPainter.width / 2,
            centerY - scaleHeight - 30,
          ),
        );
      }
    }
  }

  // 绘制当前日期指示器
  void _paintIndicator(Canvas canvas, Offset offset) {
    final centerX = offset.dx + _visibleWidth / 2;
    final centerY = offset.dy + _height / 2;
    
    // 绘制中心竖线
    canvas.drawLine(
      Offset(centerX, offset.dy + 20),
      Offset(centerX, offset.dy + _height - 20),
      Paint()
        ..color = Colors.red
        ..strokeWidth = 2.5
        ..strokeCap = StrokeCap.round,
    );
    
    // 绘制上下箭头
    const arrowSize = 10.0;
    
    // 上箭头
    final topArrow = Path();
    topArrow.moveTo(centerX - arrowSize, offset.dy + 20);
    topArrow.lineTo(centerX + arrowSize, offset.dy + 20);
    topArrow.lineTo(centerX, offset.dy + 20 - arrowSize);
    topArrow.close();
    
    // 下箭头
    final bottomArrow = Path();
    bottomArrow.moveTo(centerX - arrowSize, offset.dy + _height - 20);
    bottomArrow.lineTo(centerX + arrowSize, offset.dy + _height - 20);
    bottomArrow.lineTo(centerX, offset.dy + _height - 20 + arrowSize);
    bottomArrow.close();
    
    canvas.drawPath(topArrow, Paint()..color = Colors.red);
    canvas.drawPath(bottomArrow, Paint()..color = Colors.red);
  }

  // 绘制当前日期显示
  void _paintDateDisplay(Canvas canvas, Offset offset) {
    final dateFormatter = DateFormat('yyyy-MM-dd E');
    final dateText = dateFormatter.format(_currentDate);
    
    final textPainter = TextPainter(
      text: TextSpan(
        text: dateText,
        style: const TextStyle(
          color: Colors.black87,
          fontSize: 16,
          fontWeight: FontWeight.bold,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    textPainter.paint(
      canvas,
      Offset(
        offset.dx + (_visibleWidth - textPainter.width) / 2,
        offset.dy + 10,
      ),
    );
  }

  // 绘制背景和网格
  void _paintBackground(Canvas canvas, Offset offset) {
    // 绘制背景
    canvas.drawRect(
      offset & size,
      Paint()..color = Colors.grey[50]!,
    );
    
    // 绘制中心水平线
    final centerY = offset.dy + _height / 2;
    canvas.drawLine(
      Offset(offset.dx, centerY),
      Offset(offset.dx + _visibleWidth, centerY),
      Paint()
        ..color = Colors.grey[300]!
        ..strokeWidth = 1.0
        ..strokeCap = StrokeCap.round
        ..style = PaintingStyle.stroke
    );
  }

  // 总绘制逻辑
  @override
  void paint(PaintingContext context, Offset offset) {
    final canvas = context.canvas;
    
    canvas.save();
    
    // 1. 绘制背景
    _paintBackground(canvas, offset);
    
    // 2. 绘制日期刻度
    _paintDateScale(canvas, offset);
    
    // 3. 绘制指示器
    _paintIndicator(canvas, offset);
    
    // 4. 绘制当前日期
    _paintDateDisplay(canvas, offset);
    
    canvas.restore();
  }

  @override
  bool get isRepaintBoundary => true;
}

// 使用示例
class HundredDaysDemo extends StatelessWidget {
  const HundredDaysDemo({super.key});

  @override
  Widget build(BuildContext context) {
    // 定义起始日期（当前日期）
    final startDate = DateTime.now();
    
    return Scaffold(
      appBar: AppBar(title: const Text('100天时间刻度')),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            const Text('左右滑动选择日期（共100天范围）：'),
            const SizedBox(height: 20),
            HundredDaysTimeScale(
              visibleWidth: 350,
              height: 160,
              startDate: startDate,
              initialDate: startDate.add(const Duration(days: 10)), // 初始选中10天后
              dayPixelWidth: 50, // 每天占用50像素宽度
              showWeekday: true,
              onDateChanged: (date) {
                print('选中日期: ${DateFormat('yyyy-MM-dd').format(date)}');
              },
            ),
            const SizedBox(height: 20),
            const Text('红色指针指向的位置即为选中的日期'),
            const SizedBox(height: 10),
            const Text('• 每周一有蓝色长刻度和星期标识'),
            const Text('• 每月第一天显示月份缩写'),
            const Text('• 周末日期显示为红色'),
          ],
        ),
      ),
    );
  }
}
